{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "28521240-54bb-4602-a97a-5e3a3b9c3d48",
   "metadata": {},
   "outputs": [],
   "source": [
    "import pandas as pd\n",
    "import torch"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "a2a5b5fb-6070-4888-8bde-c10bcf377198",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 利用pandas读入数据\n",
    "train_data = pd.read_csv(\"./data/BPdata_tr.txt\")\n",
    "test_data  = pd.read_csv(\"./data/BPdata_te.txt\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "2a5d7f83-92ff-4ffa-9509-ba9f91977a7c",
   "metadata": {},
   "outputs": [],
   "source": [
    "from torch.utils.data import TensorDataset, DataLoader\n",
    "# 将数据转化成我们的tensor类型\n",
    "X_train = torch.tensor(train_data[[\"x1\", \"x2\"]].values).float()\n",
    "y_train = torch.tensor(train_data[[\"y\"]].values).float()\n",
    "\n",
    "X_test = torch.tensor(test_data[[\"x1\", \"x2\"]].values).float()\n",
    "y_test = torch.tensor(test_data[[\"y\"]].values).float()\n",
    "\n",
    "# 我们就需要将数据进行封装\n",
    "TrainData_set = TensorDataset(X_train, y_train)  #第一个参数代表输入值，第二个参数代表输出值\n",
    "TestData_set  = TensorDataset(X_test, y_test)\n",
    "\n",
    "# 数据集读取这个数据\n",
    "TrainData_loader = DataLoader(dataset = TrainData_set, batch_size = 1, shuffle = True)   # dataset 、 batch_size， shuffle"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "5f31b023-0904-484e-93c1-9d21fbd6b31a",
   "metadata": {},
   "outputs": [],
   "source": [
    "import torch.nn as nn\n",
    "class BP_Net(nn.Module):\n",
    "\n",
    "    # 在init里面写我们模型的架构\n",
    "    def __init__(self):\n",
    "        super(BP_Net, self).__init__()\n",
    "        # 架构\n",
    "        self.fc1 = nn.Linear(2, 4) #线性层, 第一层是输入层到隐藏层\n",
    "        self.fc2 = nn.Linear(4, 1) #线性层，第二层是我们的隐藏层到输出层\n",
    "\n",
    "    # 实现前向传播\n",
    "    def forward(self, x):\n",
    "        x = torch.sigmoid(self.fc1(x))\n",
    "        x = torch.sigmoid(self.fc2(x))\n",
    "        return x"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "91f0b51c-b15e-4362-9561-39f725000596",
   "metadata": {},
   "outputs": [],
   "source": [
    "import torch.optim as optim\n",
    "\n",
    "# 实例化模型\n",
    "model = BP_Net()\n",
    "# 定义损失函数和优化器\n",
    "criterion = nn.MSELoss()  #均方误差\n",
    "optimizer = optim.SGD(model.parameters(), lr = 0.85)  # 填入模型的参数和学习率"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "077bf6c7-3b74-4ec5-a794-8981831b9d41",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "现在训练了01次\n",
      "现在训练了02次\n",
      "现在训练了03次\n",
      "现在训练了04次\n",
      "现在训练了05次\n",
      "现在训练了06次\n",
      "现在训练了07次\n",
      "现在训练了08次\n",
      "现在训练了09次\n",
      "现在训练了10次\n",
      "现在训练了11次\n",
      "现在训练了12次\n",
      "现在训练了13次\n",
      "现在训练了14次\n",
      "现在训练了15次\n",
      "现在训练了16次\n",
      "现在训练了17次\n",
      "现在训练了18次\n",
      "现在训练了19次\n",
      "现在训练了20次\n",
      "现在训练了21次\n",
      "现在训练了22次\n",
      "现在训练了23次\n",
      "现在训练了24次\n",
      "现在训练了25次\n",
      "现在训练了26次\n",
      "现在训练了27次\n",
      "现在训练了28次\n",
      "现在训练了29次\n",
      "现在训练了30次\n",
      "现在训练了31次\n",
      "现在训练了32次\n",
      "现在训练了33次\n",
      "现在训练了34次\n",
      "现在训练了35次\n",
      "现在训练了36次\n",
      "现在训练了37次\n",
      "现在训练了38次\n",
      "现在训练了39次\n",
      "现在训练了40次\n",
      "现在训练了41次\n",
      "现在训练了42次\n",
      "现在训练了43次\n",
      "现在训练了44次\n",
      "现在训练了45次\n",
      "现在训练了46次\n",
      "现在训练了47次\n",
      "现在训练了48次\n",
      "现在训练了49次\n",
      "现在训练了50次\n",
      "训练结束\n"
     ]
    }
   ],
   "source": [
    "# 训练模型\n",
    "EPOCH = 50\n",
    "for epoch in range(EPOCH):\n",
    "    # 遍历我们的数据集\n",
    "    for inputs, val in TrainData_loader:\n",
    "        optimizer.zero_grad()  # 优化器梯度清零\n",
    "        output = model(inputs) # 得到目前的结果\n",
    "        # 计算损失\n",
    "        loss = criterion(output, val)  # 前面是现在的值， 后面是标准值\n",
    "        # 反向传播\n",
    "        loss.backward()\n",
    "        # 更新权重\n",
    "        optimizer.step()\n",
    "    print(\"现在训练了{:02d}次\".format(epoch + 1))\n",
    "print(\"训练结束\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "4dd5bd44-34a5-49f2-b960-9b8a95c58465",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "我们当前的模型，预测出来的误差为: 0.027378888800740242\n"
     ]
    }
   ],
   "source": [
    "# 模型评估, 用现在的模型进行预测\n",
    "# 模型的模式调为我们的eval模式\n",
    "\n",
    "model.eval()\n",
    "# 关闭梯度计算\n",
    "with torch.no_grad():\n",
    "    predictions = model(X_test)\n",
    "\n",
    "# 计算误差\n",
    "errors = predictions.flatten() - y_test.flatten()  # 预测值减去标准值\n",
    "mean_error = errors.abs().mean().item()\n",
    "print(\"我们当前的模型，预测出来的误差为: {}\".format(mean_error))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "e6184b73-a7f0-4629-ac03-00083622e22a",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.0"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
